package com.zt.questionnaire.common.utils.sign;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * 	RSA 工具类。提供加密，解密，生成密钥对等方法。
	RSA加密原理概述
	RSA的安全性依赖于大数的分解，公钥和私钥都是两个大素数（大于100的十进制位）的函数。
	据猜测，从一个密钥和密文推断出明文的难度等同于分解两个大素数的积
	密钥的产生：
	 1.选择两个大素数 p,q ,计算 n=p*q;
	 2.随机选择加密密钥 e ,要求 e 和 (p-1)*(q-1)互质
	 3.利用 Euclid 算法计算解密密钥 d , 使其满足 e*d = 1(mod(p-1)*(q-1)) (其中 n,d 也要互质)
	 4:至此得出公钥为 (n,e) 私钥为 (n,d)
	 RSA速度
 * 	由于进行的都是大数计算，使得RSA最快的情况也比DES慢上100倍，无论 是软件还是硬件实现。
 * 	速度一直是RSA的缺陷。一般来说只用于少量数据 加密。
 * @author sy
 *
 */
public class RSAUtil {
	private static Logger log = LoggerFactory.getLogger(RSAUtil.class);
    private static Cipher cipher;

    static{
        try {
            cipher = Cipher.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }

//    public static RSAKeyPair generateKeyPair() throws Exception{
//
//        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
//        // 密钥位数
//        keyPairGen.initialize(2048);
//        // 密钥对
//        KeyPair keyPair = keyPairGen.generateKeyPair();
//        // 公钥
//        PublicKey publicKey = keyPair.getPublic();
//        // 私钥
//        PrivateKey privateKey = keyPair.getPrivate();
//
//        String publicKeyString = getKeyString(publicKey);
//
//        String privateKeyString = getKeyString(privateKey);
//
//        return new RSAKeyPair(publicKeyString,privateKeyString);
//
//    }

    /**
     * 得到公钥
     *
     * @param key
     *            密钥字符串（经过base64编码）
     * @throws Exception
     */
    public static PublicKey getPublicKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    /**
     * 得到私钥
     *
     * @param key
     *            密钥字符串（经过base64编码）
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    /**
     * 得到密钥字符串（经过base64编码）
     *
     * @return
     */
    public static String getKeyString(Key key) throws Exception {
        byte[] keyBytes = key.getEncoded();
        String s = (new BASE64Encoder()).encode(keyBytes);
        return s;
    }

    /**
     * 使用公钥对明文进行加密(并进行base64的加密)
     * @param publicKey      公钥
     * @param plainText      明文
     * @return
     */
    public static String encryptBase64(String publicKey, String plainText){
        try {
            cipher.init(Cipher.ENCRYPT_MODE,getPublicKey(publicKey));
            byte[] enBytes = cipher.doFinal(plainText.getBytes());
            return (new BASE64Encoder()).encode(enBytes);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
         }
        return null;
    }

    /**
     * 使用公钥对明文进行加密
     * @param publicKey      公钥
     * @param plainText      明文
     * @return
     */
    public static String encrypt(String publicKey, String plainText){
        try {
            cipher.init(Cipher.ENCRYPT_MODE,getPublicKey(publicKey));
            byte[] enBytes = cipher.doFinal(plainText.getBytes());
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < enBytes.length; i++) {
                String hex = Integer.toHexString(enBytes[i] & 0xFF);
                if (hex.length() == 1) {
                    hex = '0' + hex;
                }
                sb.append(hex.toUpperCase());
            }
            return sb.toString();
        } catch (Exception e) {
            log.error(e.getMessage(),e);
         }
        return null;
    }

    /**
     * 使用私钥对密文进行解密
     * @param privateKey       私钥
     * @param enStr            密文
     * @return
     */
    public static String decrypt(String privateKey, String enStr){
        try {
            cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));
            byte[] deBytes = cipher.doFinal((new BASE64Decoder()).decodeBuffer(enStr));
            return new String(deBytes);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
         }
        return null;
    }

}
